
#include <stdio.h>

static inline uint8_t* 
cfers_encode_bool(uint8_t* __restrict__ out, bool b)
{
  *out = COLFERS_STATIC_CAST(uint8_t,b);
  return out+1;
}

static inline uint8_t* 
cfers_encode_enum(uint8_t* __restrict__ out, int x)
{
  return cfers_encode_int32(out, COLFERS_STATIC_CAST(int32_t,x));
}

static inline uint8_t* 
cfers_encode_int32(uint8_t* __restrict__ out, int32_t x)
{
  return cfers_encode_uint32(out, COLFERS_STATIC_CAST(uint32_t,x));
}

static inline uint8_t* 
cfers_encode_int64(uint8_t* __restrict__ out, int64_t x)
{
  return cfers_encode_uint64(out, COLFERS_STATIC_CAST(uint64_t,x));
}

static inline uint8_t* 
cfers_encode_sint32(uint8_t* __restrict__ out, int32_t x)
{
  return cfers_encode_int32(out, (x << 1) ^ (x >> 31));
}

static inline uint8_t* 
cfers_encode_sint64(uint8_t* __restrict__ out, int64_t x)
{
  return cfers_encode_int64(out, (x << 1) ^ (x >> 63));
}

static inline uint8_t* 
cfers_encode_uint32(uint8_t* __restrict__ out, uint32_t x)
{
  if (x < COLFERS_POWER_OF_TWO32(7)) {
    *(out++) = x;
  } else if (x < COLFERS_POWER_OF_TWO32(14)) {
    *(out++) = 0x80 | x;
    *(out++) = x >> 7;
  } else if (x < COLFERS_POWER_OF_TWO32(21)) {
    *(out++) = 0x80 | x;
    *(out++) = 0x80 | (x >> 7);
    *(out++) = x >> 14;
  } else if (x < COLFERS_POWER_OF_TWO32(28)) {
    *(out++) = 0x80 | x;
    *(out++) = 0x80 | (x >> 7);
    *(out++) = 0x80 | (x >> 14);
    *(out++) = x >> 21;
  } else {
    *(out++) = 0x80 | x;
    *(out++) = 0x80 | (x >> 7);
    *(out++) = 0x80 | (x >> 14);
    *(out++) = 0x80 | (x >> 21);
    *(out++) = x >> 28;
  }
  return out;
}

static inline uint8_t* 
cfers_encode_uint64(uint8_t* __restrict__ out, uint64_t x)
{
  if (x < COLFERS_POWER_OF_TWO64(35)) {
    if (x < COLFERS_POWER_OF_TWO64(7)) {
      *(out++) = x;
    } else if (x < COLFERS_POWER_OF_TWO64(14)) {
      *(out++) = 0x80 | (x & 0x7F);
      *(out++) = x >> 7;
    } else if (x < COLFERS_POWER_OF_TWO64(21)) {
      *(out++) = 0x80 | (x & 0x7F);
      *(out++) = 0x80 | ((x >> 7) & 0x7F);
      *(out++) = x >> 14;
    } else if (x < COLFERS_POWER_OF_TWO64(28)) {
      *(out++) = 0x80 | (x & 0x7F);
      *(out++) = 0x80 | ((x >> 7) & 0x7F);
      *(out++) = 0x80 | ((x >> 14) & 0x7F);
      *(out++) = x >> 21;
    } else {
      *(out++) = 0x80 | (x & 0x7F);
      *(out++) = 0x80 | ((x >> 7) & 0x7F);
      *(out++) = 0x80 | ((x >> 14) & 0x7F);
      *(out++) = 0x80 | ((x >> 21) & 0x7F);
      *(out++) = x >> 28;
    }
  } else {
    *(out++) = 0x80 | (x & 0x7F);
    *(out++) = 0x80 | ((x >> 7) & 0x7F);
    *(out++) = 0x80 | ((x >> 14) & 0x7F);
    *(out++) = 0x80 | ((x >> 21) & 0x7F);
    *(out++) = 0x80 | ((x >> 28) & 0x7F);
    x >>= 35;
    if (x < COLFERS_POWER_OF_TWO64(42)) {
      *out = x;
    } else if (x < COLFERS_POWER_OF_TWO64(49)) {
      *(out++) = 0x80 | (x & 0x7F);
      *(out++) = x >> 7;
    } else if (x < COLFERS_POWER_OF_TWO64(56)) {
      *(out++) = 0x80 | (x & 0x7F);
      *(out++) = 0x80 | ((x >> 7) & 0x7F);
      *(out++) = x >> 14;
    } else if (x < COLFERS_POWER_OF_TWO64(63)) {
      *(out++) = 0x80 | (x & 0x7F);
      *(out++) = 0x80 | ((x >> 7) & 0x7F);
      *(out++) = 0x80 | ((x >> 14) & 0x7F);
      *(out++) = x >> 21;
    } else {
      *(out++) = 0x80 | (x & 0x7F);
      *(out++) = 0x80 | ((x >> 7) & 0x7F);
      *(out++) = 0x80 | ((x >> 14) & 0x7F);
      *(out++) = 0x80 | ((x >> 21) & 0x7F);
      *(out++) = x >> 28;
    }
  }
  return out;
}

